package com.eques.https

import android.content.Context
import android.util.Log
import com.eques.database.ShaowData
import com.eques.database.dao.ShaowDao
import com.eques.event.EventTotalThread
import com.eques.icvss.utils.ELog
import com.eques.util.BaseAppApplication
import com.eques.util.Config
import com.eques.util.EquesPreference
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import org.greenrobot.eventbus.EventBus
import org.json.JSONObject
import java.io.IOException

/**
 * Created by Administrator on 2022/5/17.
 * 封装一些与阴影相关的工具类
 * @author yc
 */
class ShaowUtils private constructor(ctx: Context) {
    private val TAG = "ShaowUtils"
    private var equesPreference: EquesPreference? = null
    private var mContext: Context? = null
    private var shaowDao: ShaowDao? = null

    init {
        mContext = ctx
        equesPreference = EquesPreference(mContext!!)
        shaowDao = BaseAppApplication.instance!!.getShaowDao(mContext!!)
    }

    companion object {
        @Volatile
        private var INSTANCE: ShaowUtils? = null

        fun getInstance(context: Context): ShaowUtils {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: ShaowUtils(context).also {
                    INSTANCE = it
                }
            }
        }
    }

    /**
     * 安全获取JSON值的方法
     */
    private fun safeGetInt(json: JSONObject, key: String, defaultValue: Int = 0): Int {
        return try {
            if (json.has(key)) json.optInt(key, defaultValue) else defaultValue
        } catch (e: Exception) {
            Log.e(TAG, "Error getting int for key: $key, error: ${e.message}")
            defaultValue
        }
    }

    private fun safeGetString(json: JSONObject, key: String, defaultValue: String = ""): String {
        return try {
            if (json.has(key)) json.optString(key, defaultValue) else defaultValue
        } catch (e: Exception) {
            Log.e(TAG, "Error getting string for key: $key, error: ${e.message}")
            defaultValue
        }
    }

    /**
     * 获取影子状态
     *
     * 本函数通过HTTP请求查询并获取影子状态信息，并解析响应数据更新影子状态对象
     *
     * @param lockId 锁的唯一标识符，用于指定查询哪个锁的影子状态
     */
    fun getState(lockId: String) {
        // 获取服务器非IP地址、用户令牌和用户UID，用于构建请求URL
        val serverNonIp = equesPreference!!.getString(Config.SUB_ADDRESS)
        val token = equesPreference!!.getString(Config.EQUES_USER_TOKEN)
        val uid = equesPreference!!.getString(Config.EQUES_USER_UID)
        val userName = equesPreference!!.getString(Config.EQUES_USER_NAME)
        // 根据获取的信息构建查询影子状态的URL
        val url = Config.queryShadowStatusUrl(serverNonIp, uid, token, lockId)

        // 创建OkHttpClient实例，用于发送HTTP请求
        val client = OkHttpClient()

        // 构建请求对象，指定请求URL
        val request = Request.Builder()
            .url(url!!)
            .build()

        // 记录日志，输出当前查询影子状态的URL
        ELog.e(TAG, "getState===>$url")

        // 发送同步请求并处理响应
        try {
            client.newCall(request).execute().use { response ->
                // 如果响应不成功，抛出异常
                if (!response.isSuccessful) throw IOException("Unexpected code $response")

                val result = response.body?.string()
                EventBus.getDefault()
                    .postSticky(EventTotalThread(Config.EVENT_SHAOW_STATE, result))

                // 解析响应体为JSON对象
                val root = result?.let { JSONObject(it) } ?: run {
                    Log.e(TAG, "Response body is null or empty")
                    return
                }

                // 检查是否存在state字段
                if (!root.has("state")) {
                    Log.e(TAG, "Response does not contain 'state' field")
                    return
                }

                // 获取数据库中已有的数据
                val list = shaowDao!!.getShaow(userName!!, lockId)
                val existingShaow = if (list.isNotEmpty()) list[0] else ShaowData()

                // 创建影子状态对象，用于存储解析后的状态信息
                val shaow = ShaowData()
                shaow.id = existingShaow.id
                shaow.username = userName
                shaow.bid = lockId

                // 复制设置字段的值，避免被状态更新覆盖
                copySettingFields(existingShaow, shaow)

                // 从解析的JSON对象中获取影子状态信息，并赋值给影子状态对象
                val jsonObject = root.getJSONObject("state")

                // 使用安全方法获取字段值，如果新值为空则使用原有值
                shaow.vnum = safeGetString(jsonObject, "vnum").takeIf { it.isNotEmpty() } ?: existingShaow.vnum
                shaow.bssid = safeGetString(jsonObject, "bssid").takeIf { it.isNotEmpty() } ?: existingShaow.bssid
                shaow.is_uac = safeGetString(jsonObject, "is_uac").takeIf { it.isNotEmpty() } ?: existingShaow.is_uac
                shaow.lkmang = safeGetString(jsonObject, "lkmang").takeIf { it.isNotEmpty() } ?: existingShaow.lkmang
                shaow.video_f = safeGetString(jsonObject, "video_f").takeIf { it.isNotEmpty() } ?: existingShaow.video_f
                shaow.voltage = safeGetString(jsonObject, "voltage").takeIf { it.isNotEmpty() } ?: existingShaow.voltage
                shaow.brand_id = safeGetString(jsonObject, "brand_id").takeIf { it.isNotEmpty() } ?: existingShaow.brand_id
                shaow.no_alive = safeGetString(jsonObject, "no_alive").takeIf { it.isNotEmpty() } ?: existingShaow.no_alive
                shaow.usb_vnum = safeGetString(jsonObject, "usb_vnum").takeIf { it.isNotEmpty() } ?: existingShaow.usb_vnum
                shaow.camera_id = safeGetString(jsonObject, "camera_id").takeIf { it.isNotEmpty() } ?: existingShaow.camera_id
                shaow.door_stat = safeGetString(jsonObject, "door_stat").takeIf { it.isNotEmpty() } ?: existingShaow.door_stat
                shaow.temporary = safeGetString(jsonObject, "temporary").takeIf { it.isNotEmpty() } ?: existingShaow.temporary
                shaow.wifi_rssi = safeGetString(jsonObject, "wifi_rssi").takeIf { it.isNotEmpty() } ?: existingShaow.wifi_rssi
                shaow.wifi_ssid = safeGetString(jsonObject, "wifi_ssid").takeIf { it.isNotEmpty() } ?: existingShaow.wifi_ssid
                shaow.power_mode = safeGetString(jsonObject, "power_mode").takeIf { it.isNotEmpty() } ?: existingShaow.power_mode
                shaow.wifi_level = safeGetString(jsonObject, "wifi_level").takeIf { it.isNotEmpty() } ?: existingShaow.wifi_level
                shaow.dual_camera = safeGetString(jsonObject, "dual_camera").takeIf { it.isNotEmpty() } ?: existingShaow.dual_camera
                shaow.locked_stat = safeGetString(jsonObject, "locked_stat").takeIf { it.isNotEmpty() } ?: existingShaow.locked_stat
                shaow.locked_time = safeGetString(jsonObject, "locked_time").takeIf { it.isNotEmpty() } ?: existingShaow.locked_time
                shaow.sub_camera_id = safeGetString(jsonObject, "sub_camera_id").takeIf { it.isNotEmpty() } ?: existingShaow.sub_camera_id
                shaow.capture_rotate = safeGetString(jsonObject, "capture_rotate").takeIf { it.isNotEmpty() } ?: existingShaow.capture_rotate
                shaow.videocall_width = safeGetString(jsonObject, "videocall_width").takeIf { it.isNotEmpty() } ?: existingShaow.videocall_width
                shaow.function_support = safeGetString(jsonObject, "function_support").takeIf { it.isNotEmpty() } ?: existingShaow.function_support
                shaow.videocall_height = safeGetString(jsonObject, "videocall_height").takeIf { it.isNotEmpty() } ?: existingShaow.videocall_height

                /***********************此处只用于演示设备的参数，具体参数根据接入的类型在接口中获取***********************************/

                if (list.size > 0) {
                    shaowDao!!.updateShaow(shaow)
                    Log.e(TAG, "更新影子状态数据")
                } else {
                    shaowDao!!.insertShaow(shaow)
                    Log.e(TAG, "插入影子状态数据")
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "Error in getState: ${e.message}")
            e.printStackTrace()
        }
    }

    fun updateSetting(lockId: String, jsonObject: JSONObject) {
        // 从偏好设置中获取服务器非IP地址、用户令牌和用户ID
        val serverNonIp = equesPreference!!.getString(Config.SUB_ADDRESS)
        val token = equesPreference!!.getString(Config.EQUES_USER_TOKEN)
        val uid = equesPreference!!.getString(Config.EQUES_USER_UID)
        val userName = equesPreference!!.getString(Config.EQUES_USER_NAME)

        // 构造获取影子设置的URL
        val url = Config.updateSettingsUrl(serverNonIp, uid, token, lockId)
        ELog.e(TAG, "更新影子设置数据===>$url")

        // 创建OkHttpClient实例和请求对象
        val client = OkHttpClient()
        val jsonMediaType = "application/json; charset=utf-8".toMediaType()
        val requestBody = jsonObject.toString().toRequestBody(jsonMediaType)
        // 构建POST请求
        val request = Request.Builder()
            .url(url!!)
            .post(requestBody)
            .addHeader("Content-Type", "application/json")
            .build()

        // 发起HTTP请求并处理响应
        try {
            client.newCall(request).execute().use { response ->
                // 如果响应不成功，抛出异常
                if (!response.isSuccessful) {
                    Log.e(TAG, "更新影子设置数据失败: $response")
                } else {
                    val result = response.body?.string()
                    EventBus.getDefault()
                        .postSticky(EventTotalThread(Config.EVENT_UPDATE_SHAOW_SETTING_SUCCESS, result))
                    Log.e(TAG, "更新影子设置数据成功: $result")
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "Error in updateSetting: ${e.message}")
            e.printStackTrace()
        }
    }

    /**
     * 获取影子设置
     * 该函数负责从服务器获取特定设备（锁）的影子设置，并解析这些设置以供后续使用
     *
     * @param lockId 设备（锁）的唯一标识符，用于指定需要获取影子设置的设备
     */
    fun getSetting(lockId: String) {
        // 从偏好设置中获取服务器非IP地址、用户令牌和用户ID
        val serverNonIp = equesPreference!!.getString(Config.SUB_ADDRESS)
        val token = equesPreference!!.getString(Config.EQUES_USER_TOKEN)
        val uid = equesPreference!!.getString(Config.EQUES_USER_UID)
        val userName = equesPreference!!.getString(Config.EQUES_USER_NAME)

        // 构造获取影子设置的URL
        val url = Config.shadowSettingsQueryUrl(serverNonIp, uid, token, lockId, "")
        ELog.e(TAG, "getSetting===>$url")

        // 创建OkHttpClient实例和请求对象
        val client = OkHttpClient()
        val request = Request.Builder()
            .url(url!!)
            .build()

        // 发起HTTP请求并处理响应
        try {
            client.newCall(request).execute().use { response ->
                // 如果响应不成功，抛出异常
                if (!response.isSuccessful) throw IOException("Unexpected code $response")

                val result = response.body?.string()
                EventBus.getDefault()
                    .postSticky(EventTotalThread(Config.EVENT_SHAOW_SETTING, result))

                // 解析响应体为JSON对象
                val root = result?.let { JSONObject(it) } ?: run {
                    Log.e(TAG, "Response body is null or empty")
                    return
                }

                // 检查是否存在settings字段
                if (!root.has("settings")) {
                    Log.e(TAG, "Response does not contain 'settings' field")
                    return
                }

                // 获取数据库中已有的数据
                val list = shaowDao!!.getShaow(userName!!, lockId)
                val existingShaow = if (list.isNotEmpty()) list[0] else ShaowData()

                val shaow = ShaowData()
                shaow.id = existingShaow.id
                shaow.username = userName!!
                shaow.bid = lockId

                // 复制状态字段的值，避免被设置更新覆盖
                copyStateFields(existingShaow, shaow)

                // 从JSON对象中提取并设置影子设置的各个字段
                val jsonObject = root.getJSONObject("settings")

                // 使用安全方法获取字段值，如果新值为空则使用原有值
                shaow.alm_mod = safeGetString(jsonObject, "alm_mod").takeIf { it.isNotEmpty() } ?: existingShaow.alm_mod
                shaow.time_zone = safeGetString(jsonObject, "time_zone").takeIf { it.isNotEmpty() } ?: existingShaow.time_zone
                shaow.video_time = safeGetString(jsonObject, "video_time").takeIf { it.isNotEmpty() } ?: existingShaow.video_time
                shaow.lcd_timeout = safeGetString(jsonObject, "lcd_timeout").takeIf { it.isNotEmpty() } ?: existingShaow.lcd_timeout
                shaow.voice_count = safeGetString(jsonObject, "voice_count").takeIf { it.isNotEmpty() } ?: existingShaow.voice_count
                shaow.voice_index = safeGetString(jsonObject, "voice_index").takeIf { it.isNotEmpty() } ?: existingShaow.voice_index
                shaow.alarm_enable = safeGetString(jsonObject, "alarm_enable").takeIf { it.isNotEmpty() } ?: existingShaow.alarm_enable
                shaow.voice_status = safeGetString(jsonObject, "voice_status").takeIf { it.isNotEmpty() } ?: existingShaow.voice_status
                shaow.disturb_status = safeGetString(jsonObject, "disturb_status").takeIf { it.isNotEmpty() } ?: existingShaow.disturb_status
                shaow.alive_stop_time = safeGetString(jsonObject, "alive_stop_time").takeIf { it.isNotEmpty() } ?: existingShaow.alive_stop_time
                shaow.alive_start_time = safeGetString(jsonObject, "alive_start_time").takeIf { it.isNotEmpty() } ?: existingShaow.alive_start_time
                shaow.disturb_end_time = safeGetString(jsonObject, "disturb_end_time").takeIf { it.isNotEmpty() } ?: existingShaow.disturb_end_time
                shaow.disturb_start_time = safeGetString(jsonObject, "disturb_start_time").takeIf { it.isNotEmpty() } ?: existingShaow.disturb_start_time
                shaow.show_open_lock_button = safeGetString(jsonObject, "show_open_lock_button").takeIf { it.isNotEmpty() } ?: existingShaow.show_open_lock_button
                shaow.work_mode = safeGetString(jsonObject, "work_mode").takeIf { it.isNotEmpty() } ?: existingShaow.work_mode

                /***********************此处只用于演示设备的参数，具体参数根据接入的类型在接口中获取***********************************/

                Log.e(TAG, "更新影子设置shaow:"+shaow)
                if (list.size > 0) {
                    shaowDao!!.updateShaow(shaow)
                    Log.e(TAG, "更新影子设置数据")
                } else {
                    shaowDao!!.insertShaow(shaow)
                    Log.e(TAG, "插入影子设置数据")
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "Error in getSetting: ${e.message}")
            e.printStackTrace()
        }
    }

    /**
     * 复制影子设置字段从源对象到目标对象
     */
    private fun copySettingFields(source: ShaowData, target: ShaowData) {
        target.alm_mod = source.alm_mod
        target.time_zone = source.time_zone
        target.video_time = source.video_time
        target.lcd_timeout = source.lcd_timeout
        target.voice_count = source.voice_count
        target.voice_index = source.voice_index
        target.alarm_enable = source.alarm_enable
        target.voice_status = source.voice_status
        target.disturb_status = source.disturb_status
        target.alive_stop_time = source.alive_stop_time
        target.alive_start_time = source.alive_start_time
        target.disturb_end_time = source.disturb_end_time
        target.disturb_start_time = source.disturb_start_time
        target.show_open_lock_button = source.show_open_lock_button
        target.work_mode = source.work_mode
    }

    /**
     * 复制影子状态字段从源对象到目标对象
     */
    private fun copyStateFields(source: ShaowData, target: ShaowData) {
        target.vnum = source.vnum
        target.bssid = source.bssid
        target.is_uac = source.is_uac
        target.lkmang = source.lkmang
        target.video_f = source.video_f
        target.voltage = source.voltage
        target.brand_id = source.brand_id
        target.no_alive = source.no_alive
        target.usb_vnum = source.usb_vnum
        target.camera_id = source.camera_id
        target.door_stat = source.door_stat
        target.temporary = source.temporary
        target.wifi_rssi = source.wifi_rssi
        target.wifi_ssid = source.wifi_ssid
        target.power_mode = source.power_mode
        target.wifi_level = source.wifi_level
        target.dual_camera = source.dual_camera
        target.locked_stat = source.locked_stat
        target.locked_time = source.locked_time
        target.sub_camera_id = source.sub_camera_id
        target.capture_rotate = source.capture_rotate
        target.videocall_width = source.videocall_width
        target.function_support = source.function_support
        target.videocall_height = source.videocall_height
    }
}
